package com.eastfair.certificate.config;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.annotation.annotation.base.BaseControllerInfo;
import com.eastfair.annotation.annotation.security.PreAuth;
import com.eastfair.annotation.annotation.tenant.TenantAuth;
import com.eastfair.auth.api.AuthServiceFeign;
import com.eastfair.auth.api.UserAccountServiceFeign;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextConstants;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.context.StaticContextUtil;
import com.eastfair.core.dynamic.DynamicData;
import com.eastfair.core.exception.ForbiddenException;
import com.eastfair.core.exception.code.ExceptionCode;
import com.eastfair.core.utils.StrPool;
import com.eastfair.projectcore.enumeration.DataIsolationSystemSceneEnum;
import com.eastfair.security.aspect.VerifyAuthFunction;
import com.eastfair.security.distionarydynamic.DistionaryDynamicAnno;
import com.eastfair.security.handler.DataIsolactionHandler;
import com.eastfair.security.util.TenantUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.MDC;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.MethodParameter;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.core.annotation.Order;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.List;

import static com.eastfair.core.base.R.SUCCESS_CODE;


/**
 * controller请求切面操作
 * Created by ligang on 2010/03/02
 */
@Aspect
//@Component
@Order(3)
@Slf4j
public class UrlSecurityAspect implements ApplicationContextAware {

    /**
     * 表达式处理
     */
    private static final ExpressionParser SP_EL_PARSER = new SpelExpressionParser();
    private static final ParameterNameDiscoverer PARAMETER_NAME_DISCOVERER = new DefaultParameterNameDiscoverer();
    //    public UrlSecurityPreAuthAspect() {
//    }
    private ApplicationContext ac;

//    expression=”execution(* pp.business.*.*(..)) or execution(* pp.business.impl.*.*(..))”
    @Pointcut("execution( * com.eastfair..*.controller..*(..))")
    public void BindingResult() {
    }

    @After("BindingResult()")
    public void after(JoinPoint joinPoint) {
        log.info("after is execute");
    }

    @AfterReturning(value = "BindingResult()", returning = "rvt")
    public void AfterExec(JoinPoint joinPoint, Object rvt) {
        //controller报错不走这个方法
        log.info("AfterExec is execute");
    }

    @Around("BindingResult()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            return joinPoint.proceed();
        }
        HttpServletRequest request = attributes.getRequest();
        String url = request.getRequestURI(); // 这个方法只能获得不包含参数的请求url，且只包含相对路径
        String method = request.getMethod();
        //多租户处理
        handleTenantAuth(joinPoint);
        Object obj = joinPoint.proceed();
        return obj;
    }



    /**
     * 多租户权限
     *
     * @param joinPoint 切点isFeign
     */
    private void handleTenantAuth(ProceedingJoinPoint joinPoint) {
        //主场系统，可以看制证所有数据
        String systemScene = ContextUtil.getSystemScene();
        if (DataIsolationSystemSceneEnum.P_COMPOSITE_COURT.getCode().equals(systemScene)) {
            //主场可查询所有数据，忽略多租户
            ContextUtil.setIsSystemOlationIgnore(true);
        }else if (DataIsolationSystemSceneEnum.P_PAY.getCode().equals(systemScene)) {
            //支付系统可查询所有数据，忽略多租户
            ContextUtil.setIsSystemOlationIgnore(true);
        }else if (DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode().equals(systemScene)) {
            //综合系统可查询所有数据，忽略多租户
            ContextUtil.setIsSystemOlationIgnore(true);
        }else if (DataIsolationSystemSceneEnum.P_CERTIFICATE.getCode().equals(systemScene)) {
            //证件系统可查询所有数据，忽略多租户
            ContextUtil.setIsSystemOlationIgnore(true);
        }





    }




    @Override
    public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
        this.ac = applicationContext;
    }



}
